package com.fjwt.gz.service.activity.game.acte001;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.bo.ActivityAwardAndSettingBo;
import com.fjwt.gz.db.bo.ActivityAwardBO;
import com.fjwt.gz.db.bo.ActivityUserTimesBO;
import com.fjwt.gz.db.dto.FansActivityDTO;
import com.fjwt.gz.db.entity.ActivityAwardEntity;
import com.fjwt.gz.db.entity.ActivityEntity;
import com.fjwt.gz.db.entity.ActivityMchTimesEntity;
import com.fjwt.gz.db.entity.ActivitySettingEntity;
import com.fjwt.gz.db.entity.FansAwardEntity;
import com.fjwt.gz.db.entity.ScoreRecordTotalEntity;
import com.fjwt.gz.db.vo.ActivityAwardVO;
import com.fjwt.gz.db.vo.AwardScoreVO;
import com.fjwt.gz.db.vo.ExportAwardVO;
import com.fjwt.gz.service.activity.BaseActivityDTO;
import com.fjwt.gz.service.activity.BaseActivityService;
import com.fjwt.gz.service.activity.game.DrawUtilService;
import com.fjwt.gz.service.impl.ActivityAwardService;
import com.fjwt.gz.service.impl.ActivityMchTimesService;
import com.fjwt.gz.service.impl.ActivitySettingService;
import com.fjwt.gz.service.impl.AwardSettingService;
import com.fjwt.gz.service.impl.FansAwardService;
import com.fjwt.gz.service.impl.ScoreRecordTotalService;
import com.fjwt.gz.service.impl.SendAwardService;
import com.fjwt.gz.service.mapper.ScoreRecordTotalMapper;
import com.mysql.cj.util.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.util.TextUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 抽奖活动--商家版
 *
 * @Author Will
 * @date 2023-12-19
 */
@Slf4j
@Service
public class ACTE001Service extends BaseActivityService<Object> {

    @Autowired
    private ActivitySettingService activitySettingService;
    @Autowired
    private ActivityAwardService activityAwardService;
    @Autowired
    private ScoreRecordTotalService scoreRecordTotalService;
    @Autowired
    private ActivityMchTimesService activityMchTimesService;
    @Autowired
    private SendAwardService sendAwardService;
    @Autowired
    private DrawUtilService drawUtilService;
    @Autowired
    private FansAwardService fansAwardService;
    @Autowired
    private ScoreRecordTotalMapper recordTotalMapper;
    @Autowired
    private AwardSettingService awardSettingService;

    /**
     * 参与活动
     *
     * @return 数据异常：null; 空奖：{}；中奖：ActivityAwardVO
     */
    @Override
    public ActivityAwardVO takePartIn(FansActivityDTO fansActivityDTO) {
        log.info("进入抽奖活动--商家版活动");
        super.takePartIn(fansActivityDTO);
        Long fansId = fansActivityDTO.getFansId();
        Long activityId = fansActivityDTO.getActivityId();

        ActivityAwardVO userAwardVO;
        String activityName = activityEntity.getActivityName();
        // 检测用户参与限制条件
        JSONObject jsonObject = activitySettingService.checkActivitySetting(fansEntity, fansActivityDTO.getAppId(), redisOutTime, activityEntity);

        String currentTimesKey = String.format("%s%s:%s%s", Constants.REDIS_ACTIVITY.FILENAME, activityId, Constants.REDIS_ACTIVITY.USER_FILENAME, fansId);//用户参会活动次数redis缓存key
        log.info("每人参与的总次数redisKey:{}", currentTimesKey);
        ActivityUserTimesBO activityUserTimesBO = RedisUtil.getObject(currentTimesKey, ActivityUserTimesBO.class);//用户参会活动次数redis缓存
        log.info("每人参与的总次数redisValue:{}", JSONUtil.toJsonStr(activityUserTimesBO));

        // 检测活动基本配置
        String activitySettingKey = String.format("%s%s:%s", Constants.REDIS_ACTIVITY.FILENAME, activityId, Constants.REDIS_ACTIVITY.SETTING);
        ActivitySettingEntity activitySettingEntity = RedisUtil.getObject(activitySettingKey, ActivitySettingEntity.class);
        if (activitySettingEntity == null) {
            LambdaQueryWrapper<ActivitySettingEntity> activitySettingWrapper = new LambdaQueryWrapper<>();
            activitySettingWrapper.eq(ActivitySettingEntity::getActivityId, activityId);
            activitySettingEntity = activitySettingService.getOne(activitySettingWrapper);
            if (activitySettingEntity != null) {
                RedisUtil.set(activitySettingKey, activitySettingEntity, redisOutTime, TimeUnit.MILLISECONDS);
            }
        } else {
            log.info(String.format("活动配置表在Redis中存在，ID: %s", activityId));
        }
        if (activitySettingEntity != null) {
            if (StringUtils.isNullOrEmpty(mchNo)) {
                throw new BizException("对不起，您还没有认证商户身份");
            }
            // 参与商户是否存在
            LambdaQueryWrapper<ActivityMchTimesEntity> activityMchEntityWrapper = new LambdaQueryWrapper<>();
            activityMchEntityWrapper.eq(ActivityMchTimesEntity::getActivityId, activityId);
            activityMchEntityWrapper.eq(ActivityMchTimesEntity::getMchNo, mchNo);
            ActivityMchTimesEntity activityMchTimesEntity = activityMchTimesService.getOne(activityMchEntityWrapper);
            if (activityMchTimesEntity == null) {
                throw new BizException("对不起，您不在该活动名单范围内");
            }
            if (activityMchTimesEntity.getTimesConsume() >= activityMchTimesEntity.getTimesNum()) {
                throw new BizException("对不起，您参与活动次数已用尽");
            }

            // 参数组装
            ScoreRecordTotalEntity scoreRecordTotalEntity = new ScoreRecordTotalEntity();
            scoreRecordTotalEntity.setFlag(0);
            scoreRecordTotalEntity.setInfoId(activityId);
            scoreRecordTotalEntity.setInfoType(Constants.SCORE.ACTIVITY);
            scoreRecordTotalEntity.setAppId(fansActivityDTO.getAppId());
            scoreRecordTotalEntity.setFansId(fansId);
            scoreRecordTotalEntity.setActivityId(activityId);

            // 参加活动积分奖励
            int firstJoinScore = activitySettingEntity.getFirstJoinScore();
            int overDays = activitySettingEntity.getOverDays();
            Date overTime = activitySettingEntity.getOverTime();
            int overType = activitySettingEntity.getOverType();
            if (firstJoinScore > 0) {
                if (activityUserTimesBO != null) {
                    if (activityUserTimesBO.getTotalJoinTimes() == 1) {
                        scoreRecordTotalEntity.setScore(firstJoinScore);
                        scoreRecordTotalEntity.setName(String.format("首次参加%s奖励福分", activityName));
                        scoreRecordTotalService.addScoreRecordTotal(fansActivityDTO.getAgentNo(), scoreRecordTotalEntity, overDays, overType, overTime);
                    }
                } else {
                    activityUserTimesBO = new ActivityUserTimesBO();
                    scoreRecordTotalEntity.setScore(firstJoinScore);
                    scoreRecordTotalEntity.setName(String.format("首次参加%s奖励福分", activityName));
                    scoreRecordTotalService.addScoreRecordTotal(fansActivityDTO.getAgentNo(), scoreRecordTotalEntity, overDays, overType, overTime);
                }
            }
            int everyJoinScore = activitySettingEntity.getEveryJoinScore();
            if (everyJoinScore > 0 && overDays > 0) {
                scoreRecordTotalEntity.setScore(everyJoinScore);
                scoreRecordTotalEntity.setName(String.format("每次参加%s奖励福分", activityName));
                scoreRecordTotalService.addScoreRecordTotal(fansActivityDTO.getAgentNo(), scoreRecordTotalEntity, overDays, overType, overTime);
            }
            // 检测活动奖品配置
            String activityAwardKey = String.format("%s%s:%s", Constants.REDIS_ACTIVITY.FILENAME, activityId, Constants.REDIS_ACTIVITY.AWARD);
            List<ActivityAwardEntity> activityAwardList = RedisUtil.getObject(activityAwardKey, new com.alibaba.fastjson2.TypeReference<List<ActivityAwardEntity>>() {
            });
            if (activityAwardList == null) {
                LambdaQueryWrapper<ActivityAwardEntity> activityAwardWrapper = new LambdaQueryWrapper<>();
                activityAwardWrapper.eq(ActivityAwardEntity::getActivityId, activityId);
                activityAwardList = activityAwardService.list(activityAwardWrapper);
                if (activityAwardList != null && !activityAwardList.isEmpty()) {
                    RedisUtil.set(activityAwardKey, activityAwardList, redisOutTime, TimeUnit.MILLISECONDS);
                }
            } else {
                log.info(String.format("活动奖品配置表在Redis中存在，ID: %s", activityId));
            }
            // 进行抽奖
            List<ActivityAwardAndSettingBo> awardAndSettingBos = awardSettingService.getActivityAwardList(activitySettingEntity.getActivityId(), redisOutTime);
            Map<Long, ActivityAwardAndSettingBo> awardAndSettingBoMap = awardAndSettingBos.stream().collect(Collectors.toMap(ActivityAwardAndSettingBo::getAwardId, Function.identity()));
            ActivityAwardBO activityAwardBO = drawUtilService.draw(activitySettingEntity.getAwardType(),  awardAndSettingBos);
            if (activityAwardBO != null) {
                log.info(String.format("用户fansId:%s在本次活动activityId:%s中抽的奖品为%s", fansId, activityId, activityAwardBO.getAwardName()));
                // 积分奖品特殊处理
                if (activityAwardBO.getAwardType() == Constants.AWARD.SCORE) {
                    scoreRecordTotalEntity.setScore(activityAwardBO.getScoreValue());
                    scoreRecordTotalEntity.setName(String.format("参加%s,获得的福分奖品", activityName));
                    scoreRecordTotalService.addScoreRecordTotal(fansActivityDTO.getAgentNo(), scoreRecordTotalEntity, overDays, overType, overTime);
                } else {
                    // 增加获奖记录
                    sendAwardService.sendCouponOrGoods(fansId, fansActivityDTO.getAppId(), awardAndSettingBoMap.get(activityAwardBO.getAwardId()), activityEntity.getPayAuthId(), fansActivityDTO.getActivityChannelId(), false, fansActivityDTO.getExtJson());
                }
                userAwardVO = activityAwardService.toUserData(activityAwardBO);
            } else {
                log.info(String.format("用户fansId:%s在本次活动activityId:%s中没有中奖", fansId, activityId));
                userAwardVO = new ActivityAwardVO();
            }
            // 减少商户可参与活动次数
            activityMchTimesService.reduceNum(activityMchTimesEntity);
            // 更新Redis中参与的次数
            if (!TextUtils.isEmpty(currentTimesKey)) {
                log.info("更新个人参与次数的Redis数据,redisKey:{},redisValue:{},redisOutTime:{},TimeUnit:{}", currentTimesKey, JSONUtil.toJsonStr(activityUserTimesBO), redisOutTime, "TimeUnit.MILLISECONDS");
                RedisUtil.set(currentTimesKey, activityUserTimesBO, redisOutTime, TimeUnit.MILLISECONDS);
            }
            Boolean userJoinScoreValue = jsonObject.getObject("userJoinScoreValue", Boolean.class);
            if (ObjectUtils.isNotEmpty(userJoinScoreValue)){
                RedisUtil.set(jsonObject.getString("userJoinScoreKey"), userJoinScoreValue, redisOutTime, TimeUnit.MILLISECONDS);
            }
            return userAwardVO;
        }

        //更新Redis中参与的次数
        ActivityUserTimesBO activityUserTimes = jsonObject.getObject("activityUserTimesBO", ActivityUserTimesBO.class);
        if (ObjectUtils.isNotEmpty(activityUserTimes)){
            activitySettingService.updateRedisParticipateNum(jsonObject.getString("currentTimesKey"), activityUserTimesBO, redisOutTime);
        }

        return null;
    }

    /**
     * 新建活动
     */
    @Override
    public void add(BaseActivityDTO<Object> activityDTO) {
        log.info("新增ACTE001的活动");
        super.add(activityDTO);
    }

    /**
     * 修改活动
     */
    @Override
    public void update(BaseActivityDTO<Object> activityDTO) {
        log.info("修改ACTE001的活动");
        super.update(activityDTO);
    }

    /**
     * 删除活动
     */
    @Override
    public void delete(Long activityId) {
        log.info("删除ACTE001的活动");
        super.delete(activityId);
    }

    /**
     * 活动详情--pc
     */
    @Override
    public BaseActivityDTO detail(Long activityId) {
        log.info("查看ACTE001的活动详情");
        return super.detail(activityId);
    }

//    @Override
//    public void exportActivityAward(ActivityEntity activityEntity, HttpServletResponse response){
//        XSSFWorkbook workbook = new XSSFWorkbook();
//        List<ActivityAwardVO> awardVOS = activityAwardService.queryList(activityEntity.getActivityId());
//        // A券奖品
//        if(!awardVOS.isEmpty()){
//            for(ActivityAwardVO a:awardVOS){
//                if(0 == a.getAwardType()){
//                    List<ExportAwardVO> list = fansAwardService.exportCouponAward(a.getAwardId(),a.getRemark());
//                    ACTE001ExportExcle.createcouponsSheet(a.getAwardName(),workbook,list);
//                }else if(1== a.getAwardType()){
//                    List<ExportAwardVO> list = fansAwardService.exportGoodsAward(a.getAwardId());
//                    ACTE001ExportExcle.createGoodsSheet(a.getAwardName(),workbook,list);
//                }else if(3== a.getAwardType()){
//                    // 福分奖品
//                    List<ExportAwardVO> list = recordTotalMapper.exportScoreAward(activityEntity.getActivityId());
//                    // B2奖品信息
////                    ACTE001ExportExcle.createScoreSheet(workbook,list);
//                }
//            }
//        }else{
//            throw new BizException("该活动未配置奖品！");
//        }
//        String fileName = DateUtil.current()+".xlsx";
//        try {
//            fileName = new String(fileName.getBytes("UTF-8"),"UTF-8");
//            response.setHeader("Content-disposition", "attachment;filename=\"" + fileName + "\"");
//            OutputStream stream = response.getOutputStream();
//            if(null != workbook && null != stream){
//                workbook.write(stream);
//                workbook.close();
//                stream.close();
//            }
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }

}
